package teamproject.graphEditor;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;

import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.Graph;

/**
 * @author HaTschE
 * 
 */
public class Controller {
	/**
	 * The main method.
	 * 
	 * @param args
	 *            the arguments
	 */
	public static void main(String[] args) {
		Controller control = new Controller();
		control.init();

	}
	private GraphEditor graphEditor;
	private WelcomePanel welcome;
	private PDEEdgeFactory edgeFactory;
	private NodeFactory nodeFactory;
	private int numberOfTimesteps = 0;

	private int numberOfCells = 0;

	/**
	 * Adds the attribute.
	 * 
	 * @param attributeName
	 *            the attribute name
	 */
	public void addAttribute(String attributeName) {

		this.getEdgeFactory().addEdgeAttributeNames(attributeName);
		this.getEdgeFactory().getEdgeValues().add(0.0f);

	}

	/**
	 * Adds the attribute.
	 * 
	 * @param attributeName
	 *            the attribute name
	 * @param attributeValue
	 *            the attribute value
	 */
	public void addAttribute(String attributeName, float attributeValue) {

		this.getEdgeFactory().addEdgeAttributeNames(attributeName);
		this.getEdgeFactory().getEdgeValues().add(attributeValue);

	}

	/**
	 * Clear graph.
	 */
	public void clearGraph() {
		this.getEdgeFactory().clear();
		this.getNodeFactory().clear();
		this.getTempEdgeFactory().clear();
		this.getTempNodeFactory().clear();
		this.graphEditor.clearGraph();

	}

	/**
	 * @return returns the current edgeFactory
	 */
	@SuppressWarnings("static-access")
	public PDEEdgeFactory getEdgeFactory() {
		return edgeFactory.instance;
	}

	/**
	 * @return returns the current graphEditor
	 */
	public ArrayList<PDEEdge> getEdgesSorted() {
		SortCollectionsToArray sct = new SortCollectionsToArray();
		return sct.sortEdges(this.graphEditor.getGraph().getEdges());
	}

	/**
	 * @return returns the current graphEditor
	 */
	public DirectedGraph<Node, PDEEdge> getGraph() {
		return this.graphEditor.getGraph();
	}

	/**
	 * @return returns the current graphEditor
	 */
	public GraphEditor getGraphEditor() {
		return this.graphEditor;
	}

	/**
	 * @return returns the current nodeFactory
	 */
	@SuppressWarnings("static-access")
	public NodeFactory getNodeFactory() {
		return nodeFactory.instance;
	}

	/**
	 * @return returns the current graphEditor
	 */
	public ArrayList<Node> getNodesSorted() {
		SortCollectionsToArray sct = new SortCollectionsToArray();
		return sct.sortNodes(this.graphEditor.getGraph().getVertices());
	}

	/**
	 * @return the numberOfCells
	 */
	public int getNumberOfCells() {
		return numberOfCells;
	}

	/**
	 * @return the numberOfTimesteps
	 */
	public int getNumberOfTimesteps() {
		return numberOfTimesteps;
	}

	/**
	 * @return
	 */
	@SuppressWarnings("static-access")
	private PDEEdgeFactory getTempEdgeFactory() {
		return edgeFactory.instance2;
	}

	/**
	 * @return
	 */
	@SuppressWarnings("static-access")
	private NodeFactory getTempNodeFactory() {
		return nodeFactory.instance2;
	}

	/**
	 * @return returns the current welcomePanel
	 */
	public WelcomePanel getWelcome() {
		return welcome;
	}

	/**
	 * 
	 */
	private void init() {
		try {

			this.setNodeFactory(new NodeFactory());

			this.setEdgeFactory(new PDEEdgeFactory());

			this.setGraphEditor(new GraphEditor(getNodeFactory(),
					getEdgeFactory()));

			this.getNodeFactory().setNodes(
					this.getGraphEditor().getGraph().getVertices());

			this.setWelcome(new WelcomePanel(this));

		} catch (Exception ex) {
			String log = "ErrorLog", memory = "ErrorLog", graph = "ErrorGraph";
			File errorLog = new File("C:\\" + log + ".txt");

			int errorNumber = -1;
			while (errorLog.exists()) {
				++errorNumber;
				log = memory;
				log = log + errorNumber;
				errorLog = new File("C:\\" + log + ".txt");
			}
			graph = graph + errorNumber;
			File errorGraph = new File("C:\\" + graph);
			errorLog = new File("C:\\" + log);
			PrintWriter out;
			try {
				out = new PrintWriter(new FileWriter(errorLog + ".txt"));
				out.write(ex.toString());
				out.close();
				this.saveGraph(errorGraph, this.getGraphEditor().getGraph());
				System.exit(1);
			} catch (IOException e) {
			}
		}
	}

	public Graph<Node, PDEEdge> initNewGraph(Graph<Node, PDEEdge> graphType) {
		this.getEdgeFactory().simpleClear();
		this.getNodeFactory().clear();
		this.getTempEdgeFactory().simpleClear();
		this.getTempNodeFactory().clear();
		this.graphEditor.clearGraph();
		this.getGraphEditor().getVisualizationViewer().getGraphLayout()
				.setGraph(graphType);
		this.getNodeFactory().setNodes(graphType.getVertices());
		return graphType;
	}

	private void removeNode() {
		ArrayList<Node> toSort = new ArrayList<Node>();
		for (int i = 0; i < this.getGraphEditor().getVisualizationViewer()
				.getGraphLayout().getGraph().getVertices().size() + 1; i++) {
			toSort.add(new Node("test"));

		}
		Iterator<Node> it = this.getGraphEditor().getVisualizationViewer()
				.getGraphLayout().getGraph().getVertices().iterator();
		while (it.hasNext()) {
			Node toAdd = it.next();
			toSort.set(toAdd.getId(), toAdd);
		}
		for (int i = 0; i < toSort.size() - 1; i++) {
			if (toSort.get(i).getId() == -1) {
				int lastInt;
				if (i != 0) {
					lastInt = toSort.get(i - 1).getId();
				} else {
					lastInt = 0;
				}
				Iterator<Node> it2 = this.getGraphEditor()
						.getVisualizationViewer().getGraphLayout().getGraph()
						.getVertices().iterator();
				while (it2.hasNext()) {
					Node node = it2.next();
					if (node.getId() > lastInt) {
						node.setId(node.getId() - 1);
					}
				}
			}
		}

	}

	public void removeNode(Graph<Node, PDEEdge> graph, Node toRemove) {
		graph.removeVertex(toRemove);
		this.removeNode();
	}

	/**
	 * Save graph.
	 * 
	 * @param saveLocation
	 *            the save location
	 * @param graph
	 *            the graph
	 */
	public void saveGraph(File saveLocation, Graph<Node, PDEEdge> graph) {
		new SaveGraph(this.getGraphEditor().getGraph().getVertices(),
				saveLocation, graph, this.getGraphEditor()
						.getVisualizationViewer(), this.getEdgeFactory()
						.getEdgeValues(), this.getEdgeFactory().getLinkCount(),
				this.getNodeFactory().getNodeCount());
	}

	/**
	 * Save graph.
	 * 
	 * @param saveLocation
	 *            the save location
	 * @param graph
	 *            the graph
	 * @param edgeValues
	 *            the edge values
	 * @param nodeFactory
	 *            the node factory
	 */
	public void saveGraph(File saveLocation, Graph<Node, PDEEdge> graph,
			ArrayList<Float> edgeValues, NodeFactory nodeFactory) {
		new SaveGraph(this.getGraphEditor().getGraph().getVertices(),
				saveLocation, graph, this.getGraphEditor()
						.getVisualizationViewer(), edgeFactory.getEdgeValues(),
				edgeFactory.getLinkCount(), nodeFactory.getNodeCount());
	}

	/**
	 * @param edgeFactory
	 */
	public void setEdgeFactory(PDEEdgeFactory edgeFactory) {
		this.edgeFactory = edgeFactory;
	}

	/**
	 * @param graphEditor
	 */
	public void setGraphEditor(GraphEditor graphEditor) {
		this.graphEditor = graphEditor;
	}

	/**
	 * @param nodeFactory
	 */
	public void setNodeFactory(NodeFactory nodeFactory) {
		this.nodeFactory = nodeFactory;
	}

	/**
	 * @param numberOfCells
	 *            the numberOfCells to set
	 */
	public void setNumberOfCells(int numberOfCells) {
		this.numberOfCells = numberOfCells;
	}

	/**
	 * @param numberOfTimesteps
	 *            the numberOfTimesteps to set
	 */
	public void setNumberOfTimesteps(int numberOfTimesteps) {
		this.numberOfTimesteps = numberOfTimesteps;
	}

	/**
	 * @param welcome
	 */
	public void setWelcome(WelcomePanel welcome) {
		this.welcome = welcome;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void takeJpg(File file) {

		try {
			Thread.sleep(250);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		new ScreenShots().takeJpg(this.getGraphEditor()
				.getVisualizationViewer().getGraphLayout(), file,
				(int) this.getGraphEditor().getVisualizationViewer().getSize()
						.getWidth(), (int) this.getGraphEditor()
						.getVisualizationViewer().getSize().getHeight(),
				(int) this.getGraphEditor().getVisualizationViewer()
						.getLocationOnScreen().getX(), (int) this
						.getGraphEditor().getVisualizationViewer()
						.getLocationOnScreen().getY());
	}

}
